package com.sunsl.jobschedule.controller;

import java.util.HashMap;
import java.util.Map;

import com.sunsl.jobschedule.service.KbConsumptionRecordService;
import com.sunsl.jobschedule.job.BaseJob;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.sunsl.jobschedule.entity.JobAndTrigger;
import com.sunsl.jobschedule.entity.ResponseVO;
import com.sunsl.jobschedule.service.IJobAndTriggerService;
import com.github.pagehelper.PageInfo;


@RestController
@RequestMapping(value = "/jobSchedule")
public class JobController {
    @Autowired
    private IJobAndTriggerService iJobAndTriggerService;

    @Autowired
    private KbConsumptionRecordService kbConsumptionRecordService;

    //加入Qulifier注解，通过名称注入bean
    @Autowired
    @Qualifier("Scheduler")
    private Scheduler scheduler;

    private static Logger logger = LoggerFactory.getLogger(JobController.class);

    /**
     * 添加任务
     * @param jobClassName 任务名称
     * @param jobGroupName 任务组名称
     * @param cronExpression cron表达式
     * @throws Exception
     */
    @PostMapping(value = "/addJob")
    public ResponseVO addjob(@RequestParam(value = "jobClassName") String jobClassName,
                             @RequestParam(value = "jobGroupName") String jobGroupName,
                             @RequestParam(value = "cronExpression") String cronExpression) throws Exception {
        ResponseVO response = new ResponseVO(500, "");
        response.setMsg(addJob(jobClassName, jobGroupName, cronExpression));
        if(response.getMsg().contains("成功")){
            response.setCode(200);
        }
        return response;
    }

    private String addJob(String jobClassName, String jobGroupName, String cronExpression)  {
        String msg = "";
        String classPath = "com.cmb.xzkb.jobschedule.job.";//所有的作业类都放在该路径下
        try {
            // 启动调度器
            scheduler.start();
            //构建job信息
            JobDetail jobDetail = JobBuilder.newJob(getClass(classPath + jobClassName).getClass()).withIdentity(jobClassName, jobGroupName).build();
            //表达式调度构建器(即任务执行的时间)
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
            //按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(jobClassName, jobGroupName)
                    .withSchedule(scheduleBuilder).build();
            scheduler.scheduleJob(jobDetail, trigger);
            msg = "新增定时任务成功！";
            logger.info(msg);
        } catch (SchedulerException e) {
            msg = "创建定时任务失败" + e;
            logger.error(msg);
            //throw new Exception("创建定时任务失败");
        } catch (ClassNotFoundException e) {
            msg = "创建定时任务失败：类名未找到";
            logger.error(msg);
            //throw new Exception("创建定时任务失败");
        } catch (Exception e) {
            msg = "创建定时任务失败：cronExpression格式错误";
            logger.error(msg);
            //throw new Exception("创建定时任务失败");
        }
        return msg;
    }

    /**
     * 暂停任务
     * @param jobClassName
     * @param jobGroupName
     * @throws Exception
     */
    @PostMapping(value = "/pauseJob")
    public void pausejob(@RequestParam(value = "jobClassName") String jobClassName, @RequestParam(value = "jobGroupName") String jobGroupName) throws Exception {
        jobPause(jobClassName, jobGroupName);
        logger.info(jobClassName + "任务已暂停");
    }

    private void jobPause(String jobClassName, String jobGroupName) throws Exception {
        scheduler.pauseJob(JobKey.jobKey(jobClassName, jobGroupName));
    }

    /**
     * 恢复暂停的任务
     * @param jobClassName
     * @param jobGroupName
     * @throws Exception
     */
    @PostMapping(value = "/resumeJob")
    public void resumejob(@RequestParam(value = "jobClassName") String jobClassName, @RequestParam(value = "jobGroupName") String jobGroupName) throws Exception {
        jobresume(jobClassName, jobGroupName);
        logger.info(jobClassName + "任务已恢复运行");
    }

    private void jobresume(String jobClassName, String jobGroupName) throws Exception {
        scheduler.resumeJob(JobKey.jobKey(jobClassName, jobGroupName));
    }

    /**
     * 更新任务
     * @param jobClassName
     * @param jobGroupName
     * @param cronExpression
     * @throws Exception
     */
    @PostMapping(value = "/rescheduleJob")
    public ResponseVO rescheduleJob(@RequestParam(value = "jobClassName") String jobClassName,
                              @RequestParam(value = "jobGroupName") String jobGroupName,
                              @RequestParam(value = "cronExpression") String cronExpression)  {
        ResponseVO response = new ResponseVO(500, "");
        response.setMsg(jobreschedule(jobClassName, jobGroupName, cronExpression));
        if(response.getMsg().contains("成功")){
            response.setCode(200);
        }
        return response;
    }

    private String jobreschedule(String jobClassName, String jobGroupName, String cronExpression)  {
        String msg = "";
        try {
            TriggerKey triggerKey = TriggerKey.triggerKey(jobClassName, jobGroupName);
            // 表达式调度构建器
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
            CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
            // 按新的cronExpression表达式重新构建trigger
            trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
            // 按新的trigger重新设置job执行
            scheduler.rescheduleJob(triggerKey, trigger);
            msg = "更新定时任务成功！";
            logger.info(jobClassName + msg);
        } catch (SchedulerException e) {
            logger.error(jobClassName + "更新定时任务失败" + e);
            //throw new Exception("更新定时任务失败");
        } catch (Exception e) {
            msg = "更新定时任务失败：cronExpression格式错误";
            logger.error(jobClassName + msg);
            //throw new Exception("创建定时任务失败");
        }
        return msg;
    }

    /**
     * 删除任务
     * @param jobClassName
     * @param jobGroupName
     * @throws Exception
     */
    @PostMapping(value = "/deleteJob")
    public void deletejob(@RequestParam(value = "jobClassName") String jobClassName, @RequestParam(value = "jobGroupName") String jobGroupName) throws Exception {
        jobdelete(jobClassName, jobGroupName);
        logger.info("任务删除成功！" + jobGroupName + ":" + jobClassName);
    }

    private void jobdelete(String jobClassName, String jobGroupName) throws Exception {
        scheduler.pauseTrigger(TriggerKey.triggerKey(jobClassName, jobGroupName));
        scheduler.unscheduleJob(TriggerKey.triggerKey(jobClassName, jobGroupName));
        scheduler.deleteJob(JobKey.jobKey(jobClassName, jobGroupName));
    }

    /**
     * 分页查询所有任务列表
     * @param pageNum
     * @param pageSize
     * @return
     */
    @GetMapping(value = "/queryJob")
    public Map<String, Object> queryjob(@RequestParam(value = "pageNum") Integer pageNum, @RequestParam(value = "pageSize") Integer pageSize) {
        PageInfo<JobAndTrigger> jobAndTrigger = iJobAndTriggerService.getJobAndTriggerDetails(pageNum, pageSize);
        logger.info("查询任务列表成功！第" + pageNum + "页，共" + jobAndTrigger.getTotal() + "条");
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("JobAndTrigger", jobAndTrigger);
        map.put("number", jobAndTrigger.getTotal());
        return map;
    }

    private static BaseJob getClass(String classname) throws Exception {
        Class<?> class1 = Class.forName(classname);
        return (BaseJob) class1.newInstance();
    }
}
